﻿// -----------------------------------------------------------------------
// <copyright file="ElementPropertiesViewModel.cs" company="">
// TODO: Update copyright text.
// </copyright>
// -----------------------------------------------------------------------

namespace FormCreator.ViewModel
{
    using System;
    using System.Collections.Generic;
    using System.Collections.ObjectModel;
    using System.ComponentModel.Composition;
    using System.Linq;
    using System.Reflection;
    using System.Text;
    using FormCreator.Model;
    using Microsoft.Practices.Prism.ViewModel;
    using WPForms.Common;

    /// <summary>
    /// View model responsible for displaying properties of one element.
    /// </summary>
    [Export]
    public class ElementPropertiesViewModel : NotificationObject
    {
        /// <summary>
        /// The element whose properties are displaed.
        /// </summary>
        private object element;

        /// <summary>
        /// Initializes a new instance of the <see cref="ElementPropertiesViewModel" /> class.
        /// </summary>
        /// <param name="element">The element.</param>
        public ElementPropertiesViewModel(object element)
        {
            this.element = element;
            this.Properties = element.GetType().GetProperties()
                .Where(p => this.IsPropertyEditable(p))
                .Select(p => this.CreatePropertyItem(p))
                .ToList().AsReadOnly();
        }

        /// <summary>
        /// Gets or sets the properties.
        /// </summary>
        public ReadOnlyCollection<object> Properties { get; set; }

        /// <summary>
        /// Creates the property item for the given property.
        /// </summary>
        /// <param name="property">The property.</param>
        /// <returns>The created item.</returns>
        private object CreatePropertyItem(PropertyInfo property)
        {
            object value = null;
            if (property.PropertyType == typeof(bool))
            {
                value = new BoolElementValue(this.element, property);
            }
            else
            {
                value = new StringElementValue(this.element, property);
            }

            var description = property.GetCustomAttributes(typeof(DescriptionAttribute), true).FirstOrDefault(a => a is DescriptionAttribute) as DescriptionAttribute;
            return new
            {
                Description = description == null ? "Sets the " + property.Name + " property." : description.Description,
                Name = property.Name,
                Value = value,
            };
        }

        /// <summary>
        /// Gets if the property is editable using the designer.
        /// </summary>
        /// <param name="property">The property.</param>
        /// <returns><c>true</c> if editable; false otherwise.</returns>
        private bool IsPropertyEditable(PropertyInfo property)
        {
            var description = property.GetCustomAttributes(typeof(DescriptionAttribute), true).FirstOrDefault(a => a is DescriptionAttribute) as DescriptionAttribute;
            return description != null && description.State == System.ComponentModel.EditorBrowsableState.Always;
        }
    }
}
